package edu.chl.grupp11.aegas.controller.imp;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Observable;

import javax.swing.JOptionPane;

import edu.chl.grupp11.aegas.controller.ErrorControllerFactory;
import edu.chl.grupp11.aegas.controller.IErrorController;
import edu.chl.grupp11.aegas.controller.IFileController;
import edu.chl.grupp11.aegas.model.AbstractConfig;
import edu.chl.grupp11.aegas.model.ConfigFactory;
import edu.chl.grupp11.aegas.view.FileView;

public class FileController extends Observable implements IFileController {
	private static FileController instance = new FileController();

	public static FileController getInstance() {
		return instance;
	}

	private IErrorController errorController = ErrorControllerFactory
			.getErrorController();

	private AbstractConfig config = ConfigFactory.getSharedConfig();

	private HashMap<String, FileView> files = new HashMap<String, FileView>();

	private FileController() {
	}

	@Override
	public void addFile(File f) {
		FileView fv = new FileView(f);
		fv.addObserver(this);
		if (!hasFile(f)) {
			files.put(fv.getPath(), fv);
		} else {
			errorController.setErrorMessage(null, config.getResourceBundle()
					.getString("error5"));
			throw new IllegalArgumentException();
		}
		setChanged();
		notifyObservers();
	}

	private File changeFileName(String input, File file) {
		return new File(file.getAbsolutePath()
				.replaceAll(file.getName(), input));
	}

	@Override
	public void deleteAllFiles() {
		files.clear();
		setChanged();
		notifyObservers();
	}

	@Override
	public void deleteFile(File f) {
		files.remove(f.getAbsolutePath());
		setChanged();
		notifyObservers();
	}

	@Override
	public void deselectFilesOfWrongType(FileView chosenFile) {
		ArrayList<FileView> selectedFiles = getSelectedFiles();

		for (FileView fv : selectedFiles) {
			if (!fv.getFileType().equalsIgnoreCase(chosenFile.getFileType())) {
				fv.setSelected(false);
			}
		}
		setChanged();
		notifyObservers();
	}

	@Override
	public HashMap<String, FileView> getFiles() {
		return files;
	}

	@Override
	public FileView getFileView(File f) {
		Iterator<FileView> it = files.values().iterator();
		while (it.hasNext()) {
			FileView fv = it.next();
			if (fv.getPath().equals(f.getAbsolutePath())) {
				return fv;
			}
		}
		return null;
	}

	@Override
	public ArrayList<FileView> getSelectedFiles() {
		ArrayList<FileView> selectedFiles = new ArrayList<FileView>();
		Iterator<FileView> it = files.values().iterator();
		files = getFiles();
		while (it.hasNext()) {
			FileView fv = it.next();
			if (fv.isSelected()) {
				selectedFiles.add(fv);
			}
		}
		return selectedFiles;
	}

	@Override
	public boolean hasFile(File f) {
		return files.containsKey(f.getAbsolutePath())
				&& files.containsValue(getFileView(f));
	}

	private boolean nameExistInFolder(String fileName, File file) {
		File folder = new File(file.getAbsolutePath().replaceAll(
				file.getName(), ""));

		for (int i = 0; i < folder.listFiles().length; i++) {
			String name = folder.listFiles()[i].getName();
			if (name.equals(fileName)) {
				return true;
			}
		}
		return false;
	}

	@Override
	public void update(
			edu.chl.grupp11.aegas.utils.Observable<FileView, String> parent,
			String state) {
		errorController.setErrorMessage(null, "");
		FileView fv = (FileView) parent;
		File file = fv.getFile();
		if (state.equals("DELETE")) {
			deleteFile(file);
		} else if (state.equals("RENAME")) {
			String input = JOptionPane.showInputDialog(null,
					"New name: (Don't add an extension i.e. .jpg)",
					file.getName()
							.substring(0, file.getName().lastIndexOf('.')));
			if (input.equals("")) {
				errorController.setErrorMessage(new IOException(), config
						.getResourceBundle().getString("error17"));
			} else if (input != "-1") {
				if (nameExistInFolder(input, file)) {
					errorController.setErrorMessage(new IOException(), config
							.getResourceBundle().getString("error18"));
				} else {
					String name = input
							+ file.getName()
									.substring(file.getName().lastIndexOf('.'))
									.toLowerCase();
					File newFile = changeFileName(name, file);

					deleteFile(file);
					if (file.renameTo(newFile)) {
						addFile(newFile);
					} else {
						addFile(file);
					}
				}
			}
		} else if (state.equals("CLICK")) {
			if (file.exists()) {
				if (fv.isSelected()) {
					fv.setSelected(false);
				} else {
					fv.setSelected(true);
				}
				deselectFilesOfWrongType(fv);
			} else {
				errorController
						.setErrorMessage(null, "\""
								+ file.getName()
								+ "\""
								+ config.getResourceBundle()
										.getString("error8"));
				deleteFile(file);
			}
		}
	}
}
